﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Diagnostics;

namespace IRC.NET.Net
{
    public abstract class ServerConnectionBase
    {
        private TcpClient _socket;
        private StreamReader _reader;
        private StreamWriter _writer;

        private bool _connected = false;

        public bool IsConnected
        {
            get
            {
                return (this._connected);
            }
        }

        public ServerConnectionBase()
        {
            try
            {
                this._connected = false;
                this._socket = new TcpClient();
                //this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IPv4);
            }
            catch (Exception e)
            {
                throw new ServerConnectionException("Unable to create server connection socket.", e);
            }
        }

        protected void Connect(IPAddress address, int port)
        {
            if (address == null)
            {
                throw new ArgumentNullException("IP Address cannot be null.");
            }
            else if (port < 1)
            {
                throw new ArgumentException("Port must be greater than 1");
            }

            try
            {
                this._socket.Connect(address, port);

                NetworkStream networkStream = this._socket.GetStream();
                this._reader = new StreamReader(networkStream);
                this._writer = new StreamWriter(networkStream);

                this._connected = true;
            }
            catch (Exception e)
            {
                this._connected = false;
                throw new ServerConnectionException(string.Format("Unable to connect to {0}:{1}", address.ToString(), port.ToString()), e);
            }
        }

        protected void Send(string message)
        {
            if (!this.IsConnected)
            {
                throw new ServerConnectionException("Could not send. The socket is not connected.");
            }
            else if (this._reader == null)
            {
                throw new ServerConnectionException("Writer is not opened correctly.");
            }

            Debug.WriteLine(message);
            this._writer.Write(message);
            this._writer.Flush(); // Make sure this message makes it out!
        }

        protected string Recieve()
        {
            if (!this.IsConnected)
            {
                throw new ServerConnectionException("Could not recieve. The socket is not connected.");
            }
            else if (this._reader == null)
            {
                throw new ServerConnectionException("Reader is not opened correctly.");
            }
            
            return (this._reader.ReadLine());
        }

        public virtual void Close()
        {
            if (!(this._reader == null))
            {
                this._reader.Close();
            }

            if (!(this._writer == null))
            {
                this._writer.Close();
            }

            if (!(this._socket == null))
            {
                this._socket.Close();
            }

            this._connected = false;
        }
    }
}
